//
//  UIButton+Extension.m
//  TableDemo
//
//  Created by jutuo on 2020/3/29.
//  Copyright © 2020 jutuo. All rights reserved.
//

#import "UIButton+Extension.h"
#import <objc/runtime.h>
#import "NSObject+Extension.h"
#import "UIView+Extension.h"
@interface UIButton ()
@property (nonatomic, strong) UIColor *normalBgColor;
@property (nonatomic, strong) UIColor *highlightedBgColor;
@property (nonatomic, strong) UIColor *selectedBgColor;

@property (nonatomic, strong) UIColor *normalBorderColor;
@property (nonatomic, strong) UIColor *highlightedBorderColor;
@property (nonatomic, strong) UIColor *selectedBorderColor;

@property (nonatomic, assign) CGFloat normalBorderWidth;
@property (nonatomic, assign) CGFloat highlightBorderWidth;
@property (nonatomic, assign) CGFloat selectedBorderWidth;
@end
@implementation UIButton (Extension)
+ (void)load
{
    [self swizzleInstanceMethod:@selector(init) with:@selector(xy_init)];
    [self swizzleClassMethod:@selector(buttonWithType:) with:@selector(xy_buttonWithType:)];
    [self swizzleInstanceMethod:@selector(layoutSubviews) with:@selector(xy_layoutSubviews)];
    [self swizzleInstanceMethod:@selector(setTitle:forState:) with:@selector(xy_setTitle:forState:)];
    [self swizzleInstanceMethod:@selector(setImage:forState:) with:@selector(xy_setImage:forState:)];
    [self swizzleInstanceMethod:@selector(sizeThatFits:) with:@selector(xy_sizeThatFits:)];
    [self swizzleInstanceMethod:@selector(setSelected:) with:@selector(xy_setSelected:)];
    [self swizzleInstanceMethod:@selector(setBackgroundColor:) with:@selector(xy_setBackgroundColor:)];
}

- (void)dealloc
{
    [self removeAllObserverBlocks];
}
- (instancetype)xy_init
{
    WeakSelf(self);
    [self addObserverBlockForKeyPath:@"state" block:^(__weak id  _Nonnull obj, id  _Nonnull oldVal, id  _Nonnull newVal) {
        StrongSelf(self);
        [self setBgColor];
        [self setBorderColor];
        [self setBorderWidth];
    }];
    return [self xy_init];
}

+ (instancetype)xy_buttonWithType:(UIButtonType)type
{
    id btn = [self xy_buttonWithType:type];
    WeakSelf(btn);
    [btn addObserverBlockForKeyPath:@"state" block:^(__weak id  _Nonnull obj, id  _Nonnull oldVal, id  _Nonnull newVal) {
        StrongSelf(btn);
        [btn setBgColor];
        [btn setBorderColor];
        [btn setBorderWidth];
    }];
    return btn;
}

- (void)xy_setSelected:(BOOL)selected
{
    [self xy_setSelected:selected];
    [self willChangeValueForKey:@"state"];
    [self didChangeValueForKey:@"state"];
}

- (UIButtonTitleImageRelativePosition)positionType
{
    return [objc_getAssociatedObject(self, _cmd) integerValue];
}

- (void)setPositionType:(UIButtonTitleImageRelativePosition)positionType
{
    objc_setAssociatedObject(self, @selector(positionType), @(positionType), OBJC_ASSOCIATION_ASSIGN);
    if (positionType == OnlyTitle) {
        [self.imageView removeFromSuperview];
        [self addSubview:self.titleLabel];
    }else if (positionType == OnlyImage){
        [self addSubview:self.imageView];
        [self.titleLabel removeFromSuperview];
    }else{
        [self addSubview:self.imageView];
        [self addSubview:self.titleLabel];
    }
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (CGFloat)space
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}

- (void)setSpace:(CGFloat)space
{
    objc_setAssociatedObject(self, @selector(space), @(space), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (NSString *)titleText
{
    return objc_getAssociatedObject(self, _cmd);
}
-(void)setTitleText:(NSString *)titleText
{
    objc_setAssociatedObject(self, @selector(titleText), titleText, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self setTitle:titleText forState:UIControlStateNormal];
    
}

- (void)xy_setTitle:(NSString *)title forState:(UIControlState)state
{
    objc_setAssociatedObject(self, @selector(titleText), title, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self xy_setTitle:title forState:state];
    
    [self setNeedsLayout];
    [self layoutIfNeeded];
}
- (NSString *)imgName
{
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setImgName:(NSString *)imgName
{
    objc_setAssociatedObject(self, @selector(imgName), imgName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    UIImage *image = [UIImage imageNamed:imgName];
    [self setImage:image forState:UIControlStateNormal];
//    CGSize imgSize = image.size;
//
//    self.imageView.frame = CGRectMake(0, 0, imgSize.width, imgSize.height);
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (void)xy_setImage:(UIImage *)image forState:(UIControlState)state
{
    [self xy_setImage:image forState:state];
    
    [self setNeedsLayout];
    [self layoutIfNeeded];
}
- (UIFont *)titleFont
{
    return self.titleLabel.font;
}

- (void)setTitleFont:(UIFont *)titleFont
{
    self.titleLabel.font = titleFont;
    
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (UIButtonContentAlignmentType)aliginment
{
    return [objc_getAssociatedObject(self, _cmd) integerValue];
}

- (void)setAliginment:(UIButtonContentAlignmentType)aliginment
{
    objc_setAssociatedObject(self, @selector(aliginment), @(aliginment), OBJC_ASSOCIATION_ASSIGN);
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (CGFloat)hPadding
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}
- (void)setHPadding:(CGFloat)hPadding
{
    objc_setAssociatedObject(self, @selector(hPadding), @(hPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (self.aliginment != AlignmentTypeNone && self.aliginment != AlignmentTypeStrut) {
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }
    
}

- (CGFloat)vPadding
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}

- (void)setVPadding:(CGFloat)vPadding
{
    objc_setAssociatedObject(self, @selector(vPadding), @(vPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (self.aliginment != AlignmentTypeNone && self.aliginment != AlignmentTypeStrut) {
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }
}

- (CGFloat)ltPadding
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}

- (void)setLtPadding:(CGFloat)ltPadding
{
    objc_setAssociatedObject(self, @selector(ltPadding), @(ltPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (self.aliginment == AlignmentTypeStrut) {
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }
}

- (CGFloat)rbPadding
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}

- (void)setRbPadding:(CGFloat)rbPadding
{
    objc_setAssociatedObject(self, @selector(rbPadding), @(rbPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (self.aliginment == AlignmentTypeStrut) {
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }
}
- (void)setAnimationImages:(NSArray<UIImage *> *)animationImages animationDuration:(NSTimeInterval)animationDuration
{
    UIImage *animationImage = [UIImage animatedImageWithImages:animationImages duration:animationDuration];
    [self setImage:animationImage forState:UIControlStateNormal];
    [self setImage:animationImage forState:UIControlStateHighlighted];
}
// background color
- (void)xy_setBackgroundColor:(UIColor *)color
{
    self.normalBgColor = color;
    [self xy_setBackgroundColor:color];
}
- (UIColor *)normalBgColor
{
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setNormalBgColor:(UIColor *)normalBgColor
{
    objc_setAssociatedObject(self, @selector(normalBgColor), normalBgColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIColor *)highlightedBgColor
{
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setHighlightedBgColor:(UIColor *)highlightedBgColor
{
    objc_setAssociatedObject(self, @selector(highlightedBgColor), highlightedBgColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIColor *)selectedBgColor
{
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setSelectedBgColor:(UIColor *)selectedBgColor
{
    objc_setAssociatedObject(self, @selector(selectedBgColor), selectedBgColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state
{
    switch (state) {
        case UIControlStateNormal:
            self.normalBgColor = backgroundColor;
            break;
        case UIControlStateHighlighted:
            self.highlightedBgColor = backgroundColor;
            break;
        case UIControlStateDisabled:
            
            break;
        case UIControlStateSelected:
            self.selectedBgColor = backgroundColor;
            break;
        case UIControlStateFocused:
            
            break;
        case UIControlStateApplication:
            
            break;
        case UIControlStateReserved:
            
            break;
        default:
            break;
    }
    [self setBgColor];
}
- (void)setBgColor
{
    switch (self.state) {
        case UIControlStateNormal:
            [self xy_setBackgroundColor:self.normalBgColor];
            break;
        case UIControlStateHighlighted:
        {
            UIColor *color = self.highlightedBgColor ? self.highlightedBgColor : self.normalBgColor;
            [self xy_setBackgroundColor:color];

        }
            break;
        case UIControlStateDisabled:
            
            break;
        case UIControlStateSelected:
        {
            UIColor *color = self.selectedBgColor ? self.selectedBgColor : self.normalBgColor;
            [self xy_setBackgroundColor:color];

        }
            break;
        case UIControlStateHighlighted | UIControlStateSelected:
        {
            UIColor *color = self.selectedBgColor ? self.selectedBgColor : self.normalBgColor;
            [self xy_setBackgroundColor:color];
        }
            break;
        case UIControlStateFocused:
            
            break;
        case UIControlStateApplication:
            
            break;
        case UIControlStateReserved:
            
            break;
        default:
            break;
    }
}

/**
 * border color
 */
- (UIColor *)normalBorderColor
{
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setNormalBorderColor:(UIColor *)normalBorderColor
{
    objc_setAssociatedObject(self, @selector(normalBorderColor), normalBorderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIColor *)highlightedBorderColor
{
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setHighlightedBorderColor:(UIColor *)highlightedBorderColor
{
    objc_setAssociatedObject(self, @selector(highlightedBorderColor), highlightedBorderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIColor *)selectedBorderColor
{
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setSelectedBorderColor:(UIColor *)selectedBorderColor
{
    objc_setAssociatedObject(self, @selector(selectedBorderColor), selectedBorderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)setBorderColor:(UIColor *)color forState:(UIControlState)state
{
    switch (state) {
        case UIControlStateNormal:
            self.normalBorderColor = color;
            break;
        case UIControlStateHighlighted:
            self.highlightedBorderColor = color;
            break;
        case UIControlStateDisabled:
            
            break;
        case UIControlStateSelected:
            self.selectedBorderColor = color;
            break;
        case UIControlStateFocused:
            
            break;
        case UIControlStateApplication:
            
            break;
        case UIControlStateReserved:
            
            break;
        default:
            break;
    }
    [self setBorderColor];
}
- (void)setBorderColor
{
    switch (self.state) {
        case UIControlStateNormal:
            self.layer.borderColor = self.normalBorderColor.CGColor;
            break;
        case UIControlStateHighlighted:
        {
            UIColor *color = self.highlightedBorderColor ? self.highlightedBorderColor : self.normalBorderColor;
            self.layer.borderColor = color.CGColor;

        }
            break;
        case UIControlStateDisabled:
            
            break;
        case UIControlStateSelected:
        {
            UIColor *color = self.selectedBorderColor ? self.selectedBorderColor : self.normalBorderColor;
            self.layer.borderColor = color.CGColor;

        }
            break;
        case UIControlStateFocused:
            
            break;
        case UIControlStateApplication:
            
            break;
        case UIControlStateReserved:
            
            break;
        default:
            break;
    }
}

/**
 * border width
 */
- (CGFloat)normalBorderWidth
{
    return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setNormalBorderWidth:(CGFloat)normalBorderWidth
{
    objc_setAssociatedObject(self, @selector(normalBorderWidth), @(normalBorderWidth), OBJC_ASSOCIATION_ASSIGN);
}

- (CGFloat)highlightBorderWidth
{
    return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setHighlightBorderWidth:(CGFloat)highlightBorderWidth
{
    objc_setAssociatedObject(self, @selector(highlightBorderWidth), @(highlightBorderWidth), OBJC_ASSOCIATION_ASSIGN);
}

- (CGFloat)selectedBorderWidth
{
    return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setSelectedBorderWidth:(CGFloat)selectedBorderWidth
{
    objc_setAssociatedObject(self, @selector(selectedBorderWidth), @(selectedBorderWidth), OBJC_ASSOCIATION_ASSIGN);
}
- (void)setBorderWidth:(CGFloat)borderWidth forState:(UIControlState)state
{
    switch (state) {
        case UIControlStateNormal:
            self.normalBorderWidth = borderWidth;
            break;
        case UIControlStateHighlighted:
            self.highlightBorderWidth = borderWidth;
            break;
        case UIControlStateDisabled:
            
            break;
        case UIControlStateSelected:
            self.selectedBorderWidth = borderWidth;
            break;
        case UIControlStateFocused:
            
            break;
        case UIControlStateApplication:
            
            break;
        case UIControlStateReserved:
            
            break;
        default:
            break;
    }
    [self setBorderWidth];
}
- (void)setBorderWidth
{
    switch (self.state) {
        case UIControlStateNormal:
            self.layer.borderWidth = self.normalBorderWidth;
            break;
        case UIControlStateHighlighted:
            self.layer.borderWidth = self.highlightBorderWidth ? self.highlightBorderWidth :  self.normalBorderWidth;
            break;
        case UIControlStateDisabled:
            
            break;
        case UIControlStateSelected:
            self.layer.borderWidth = self.selectedBorderWidth ? self.selectedBorderWidth : self.normalBorderWidth;
            break;
        case UIControlStateFocused:
            
            break;
        case UIControlStateApplication:
            
            break;
        case UIControlStateReserved:
            
            break;
        default:
            break;
    }
    
}


- (void)xy_layoutSubviews
{
    [self xy_layoutSubviews];
    if (self.positionType == UIButtonDefault) {
        return;
    }
    CGSize titleSize = [self.titleText sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}];
    self.titleLabel.width = titleSize.width;
    self.titleLabel.height = titleSize.height;
    
    CGSize imgSize = self.imageView.image.size;
    self.imageView.width = imgSize.width;
    self.imageView.height = imgSize.height;
    
    UIButtonContentAlignmentType hAlign = self.aliginment & (AlignmentTypeLeft | AlignmentTypeRight);
    UIButtonContentAlignmentType vAlign = self.aliginment & (AlignmentTypeTop | AlignmentTypeBottom);
    if (self.positionType == OnlyTitle) {
        CGFloat titleWidth = self.titleLabel.width;
        CGFloat titleHeight = self.titleLabel.height;
        CGFloat originX = (hAlign == AlignmentTypeNone) ? (self.width - titleWidth) / 2.0 : (hAlign == AlignmentTypeLeft) ? self.hPadding : self.width - self.hPadding - titleWidth;
        CGFloat originY = (vAlign == AlignmentTypeNone) ? (self.height - titleHeight) / 2.0 : (vAlign == AlignmentTypeTop) ? self.vPadding : self.height - titleHeight - self.vPadding;
        self.titleLabel.origin = CGPointMake(originX, originY);
    }else if (self.positionType == OnlyImage){
        CGFloat imageWidth = self.imageView.width;
        CGFloat imageHeight = self.imageView.height;
        CGFloat originX = (hAlign == AlignmentTypeNone) ? (self.width - imageWidth) / 2.0 : (hAlign == AlignmentTypeLeft) ? self.hPadding : self.width - self.hPadding - imageWidth;
        CGFloat originY = (vAlign == AlignmentTypeNone) ? (self.height - imageHeight) / 2.0 : (vAlign == AlignmentTypeTop) ? self.vPadding : self.height - imageHeight - self.vPadding;
        self.imageView.origin = CGPointMake(originX, originY);
    }else if (self.positionType == TitleLeftImageRight || self.positionType == ImageLeftTitleRight) {
        if (self.aliginment == AlignmentTypeStrut) {
            self.titleLabel.x =  (self.positionType == TitleLeftImageRight) ? self.ltPadding : self.width - self.rbPadding - self.titleLabel.width;
            self.titleLabel.centerY = self.height/2.0;
            
            self.imageView.x = (self.positionType == TitleLeftImageRight) ? self.width - self.rbPadding - self.imageView.width : self.ltPadding;
            self.imageView.centerY = self.height/2.0;
        }else{
            CGFloat len = self.titleLabel.width + self.space + self.imageView.width;
            CGFloat originX = (hAlign == AlignmentTypeNone) ? (self.width - len) / 2.0 : (hAlign == AlignmentTypeLeft) ? self.hPadding : self.width - self.hPadding - len;
           CGFloat TitleImageOffY = (self.titleLabel.height - self.imageView.height)/2.0;
           CGFloat titleOriginY = (vAlign == AlignmentTypeNone)  ? (self.height - self.titleLabel.height)/2.0 : (vAlign == AlignmentTypeTop) ? (TitleImageOffY > 0) ? self.vPadding : self.vPadding + fabs(TitleImageOffY) : (TitleImageOffY > 0) ? self.height - self.vPadding - self.titleLabel.height : self.height - self.vPadding - self.titleLabel.height - + fabs(TitleImageOffY);
           CGFloat imageOriginY =(vAlign == AlignmentTypeNone)  ? (self.height - self.imageView.height)/2.0 : (vAlign == AlignmentTypeTop) ? (TitleImageOffY > 0) ? self.vPadding + fabs(TitleImageOffY) : self.vPadding : (TitleImageOffY > 0) ? self.height - self.vPadding - self.imageView.height - fabs(TitleImageOffY): self.height - self.vPadding - self.imageView.height ;
           
           self.titleLabel.x =  (self.positionType == TitleLeftImageRight) ? originX : originX + self.imageView.width + self.space;
           self.titleLabel.y = titleOriginY;
           
           self.imageView.x = (self.positionType == TitleLeftImageRight) ? originX + self.titleLabel.width + self.space : originX;
           self.imageView.y = imageOriginY;
        }
        
    }else if (self.positionType == ImageTopTitleBottom || self.positionType == TitleTopImageBottom){
        if (self.aliginment == AlignmentTypeStrut) {
            self.titleLabel.y =  (self.positionType == TitleTopImageBottom) ? self.ltPadding : self.height - self.rbPadding - self.titleLabel.height;
            self.titleLabel.centerX = self.width/2.0;
            
            self.imageView.y = (self.positionType == TitleTopImageBottom) ? self.height - self.rbPadding - self.imageView.height : self.ltPadding;
            self.imageView.centerX = self.width/2.0;
        }else{
            CGFloat height = self.titleLabel.height + self.space + self.imageView.height;
            CGFloat originY = (vAlign == AlignmentTypeNone) ? (self.height - height) / 2.0 : (vAlign == AlignmentTypeTop) ? self.vPadding : self.height - height - self.vPadding;
            
            CGFloat TitleImageOffY = (self.titleLabel.width - self.imageView.width)/2.0;
            CGFloat titleOriginX = (hAlign == AlignmentTypeNone) ? (self.width - self.titleLabel.width)/2.0 : (hAlign == AlignmentTypeLeft) ? (TitleImageOffY > 0) ? self.hPadding : self.hPadding + fabs(TitleImageOffY) : (TitleImageOffY > 0) ? self.width - TitleImageOffY - self.titleLabel.width : self.width - TitleImageOffY - self.titleLabel.width - fabs(TitleImageOffY);
            
            CGFloat imageOriginX = (hAlign == AlignmentTypeNone) ? (self.width - self.imageView.width)/2.0 : (hAlign == AlignmentTypeLeft) ? (TitleImageOffY > 0) ? self.hPadding + fabs(TitleImageOffY) : self.hPadding : (TitleImageOffY > 0) ? self.width - TitleImageOffY - self.imageView.width - fabs(TitleImageOffY) : self.width - TitleImageOffY - self.imageView.width;
            
            self.titleLabel.x = titleOriginX;
            self.titleLabel.y = (self.positionType == TitleTopImageBottom) ? originY :  originY + self.imageView.height + self.space;
            
            self.imageView.x = imageOriginX;
            self.imageView.y = (self.positionType == TitleTopImageBottom) ? originY + self.titleLabel.height + self.space : originY;
        }
        
    }
}

//获取内容的宽高
- (CGSize)xy_sizeThatFits:(CGSize)size
{
    size = [self xy_sizeThatFits:size];
    if (self.positionType == OnlyTitle) {
        size = self.titleLabel.size;
    }else if (self.positionType == OnlyImage){
        size = self.imageView.size;
    }else if (self.positionType == TitleLeftImageRight || self.positionType == ImageLeftTitleRight) {
        CGFloat len = self.titleLabel.width + self.space + self.imageView.width;
        CGFloat height = self.titleLabel.height > self.imageView.height ? self.titleLabel.height : self.imageView.height;
        size = CGSizeMake(len, height);
    }else if (self.positionType == ImageTopTitleBottom || self.positionType == TitleTopImageBottom){
        CGFloat height = self.titleLabel.height + self.space + self.imageView.height;
        CGFloat len = self.titleLabel.width > self.imageView.width ? self.titleLabel.width : self.imageView.width;
        size = CGSizeMake(len, height);
    }
    
    return size;
}

static const NSString *timeOutKey = @"timeOutKey";
- (void)setTimeOut:(NSInteger)timeOut
{
    objc_setAssociatedObject(self, &timeOut, @(timeOut), OBJC_ASSOCIATION_ASSIGN);
}
- (NSInteger)timeOut
{
    NSNumber *timeOutNum = objc_getAssociatedObject(self, &timeOutKey);
    return [timeOutNum integerValue];
}
- (void)verifedCodeButtonWithTitle:(NSString *_Nullable)title andNewTitle:(NSString *_Nullable)newTitle titleColor:(UIColor * _Nullable)titleColor  newTitleColor:(UIColor * _Nullable)newTitleColor bgColor:(UIColor * _Nullable)bgColor newBgColor:(UIColor *_Nullable)newBgColor
{
    __weak typeof(self) weakSelf = self;
    __block NSInteger timeout = self.timeOut ? self.timeOut : 60;
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(timer, ^{
        if (timeout <= 0) {
            dispatch_source_cancel(timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                if (title) {
                    [weakSelf setTitle:title forState:UIControlStateNormal];
                }
                if (titleColor) {
                    [weakSelf setTitleColor:titleColor forState:UIControlStateNormal];
                }
                if (bgColor) {
                    weakSelf.backgroundColor = bgColor;
                }
                weakSelf.userInteractionEnabled = YES;
            });
        } else{
            NSString *strTime = [NSString stringWithFormat:@"%.2ld", (long)timeout];
            dispatch_async(dispatch_get_main_queue(), ^{
                
                if (newTitle) {
                    [weakSelf setTitle:[NSString stringWithFormat:@"%@(%@)",newTitle, strTime] forState:UIControlStateNormal];
                }
                if (newTitleColor) {
                    [weakSelf setTitleColor:newTitleColor forState:UIControlStateNormal];
                }
                if (newBgColor) {
                    weakSelf.backgroundColor = newBgColor;
                }
            
                weakSelf.userInteractionEnabled = NO;
            });
            
            timeout--;
        }
    });
    dispatch_resume(timer);
    
}

@end


#import "NSObject+Extension.h"
@interface UIButton ()
@property (nonatomic, assign) NSTimeInterval acceptEventTime;
@end
@implementation UIButton (XDClickInterval)
+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleInstanceMethod:@selector(sendAction:to:forEvent:) with:@selector(XD_sendAction:to:forEvent:)];
    });
}
- (NSTimeInterval)acceptEventInterval
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}

- (void)setAcceptEventInterval:(NSTimeInterval)acceptEventInterval
{
    objc_setAssociatedObject(self, @selector(acceptEventInterval), @(acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSTimeInterval)acceptEventTime
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}

- (void)setAcceptEventTime:(NSTimeInterval)acceptEventTime
{
    objc_setAssociatedObject(self, @selector(acceptEventTime), @(acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)XD_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    if ([NSDate date].timeIntervalSince1970 - self.acceptEventTime < self.acceptEventInterval) {
        return;
    }
    
    self.acceptEventTime = [NSDate date].timeIntervalSince1970;
    
    [self XD_sendAction:action to:target forEvent:event];
}

@end
